package com.zdb.java.io;

import org.junit.Test;

import java.nio.ByteBuffer;

public class DirectByteBufTest {

    /**
     * 测试DirectByteBuffer中对堆外的释放机制，
     *
     * 1. DirectByteBuffer在初始化时，先尝试去是否可以允许申请内存 Bits.reserveMemory(size, cap);
     * 2. Bits.reserveMemory(size, cap); 如果堆外内存可用容量够就设置已申请内存+size,
     *    如果不够，会去释放那些已经被回收的DirectByteBuffer的堆外内存，
     *    如果还不够，调用System.gc(),来回收没用的DirectByteBuffer，
     *    然后循环9次，{每次都自行释放已被回收的DirectByteBuffer的堆外内存，再尝试申请，申请不到，
     *    Thread.sleep,sleep时间从1,2,4,8 2的n次方累加}
     *    如果还申请不到就报异常OutOfMemoryError("Direct buffer memory")
     * 3. 允许通过，unsafe.allocateMemory(size);
     * 4. 生成Cleaner对象，实现了runnable接口，对象里有申请的堆外内存地址，该对象为 PhantomReference类型，
     *    会在DirectByteBuffer被垃圾回收后，把cleaner加入到一个ReferenceQueue，然后会被执行
     *
     *
     */
    @Test
    public void test1() {
        int cnt = 1;
        for (int i = 0; i < 9; i++) {
            System.out.println(cnt<<=1);
        }

        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(100);
        byteBuffer.put((byte)'a');
    }
}
